<script setup lang="ts">
import type { FormInstance, FormValidateCallback, UploadFiles } from 'element-plus'
import type { Banner } from './type'
import { uploadFile } from '@/api'

const baseApi = '/ea/banner'

defineProps<{
  // 禁用表单内的所有组件
  disabled?: boolean
  // 禁用属性列表（只读不可输入）
  disabledProps?: string[]
  // 不可见属性列表（忽略不加载）
  invisibleProps?: string[]
}>()

const emit = defineEmits<{
  (e: 'complete', id?: string, isNew?: boolean): void
  (e: 'submitting', submitting: boolean): void
}>()

const { initRelatedData, relatedData } = useOption({
  dict: ['client_type']
})
const { loadData, loading, model } = useDetail<Banner>(baseApi)

const { submitting, submit } = useForm({ baseApi, successCallback: (id, isNew) => emit('complete', id, isNew) })
watch(submitting, value => emit('submitting', value))

//  表单
const formRef = ref<FormInstance>()

const image = ref<UploadFiles>([])
const handleImageFileRemove = (file, fileList) => {
  image.value = fileList.filter(item => item.uid !== file.uid)
  model.value.image = '' // 移除文件时清空表单中的值
}
const imageUpload = async options => {
  try {
    const res = await uploadFile(options.file)
    if (res.data) {
      model.value.image = res.data
      ElMessage.success('上传成功')
    }
  } catch (error) {
    ElMessage.error('上传失败')
    // 上传失败时移除文件
    const index = image.value.findIndex(item => item.uid === options.file.uid)
    if (index !== -1) {
      image.value.splice(index, 1)
    }
  }
}

const content = ref<UploadFiles>([])

const handleContentFileRemove = (file, fileList) => {
  content.value = fileList.filter(item => item.uid !== file.uid)
  model.value.content = '' // 移除文件时清空表单中的值
}
const contentUpload = async options => {
  try {
    const res = await uploadFile(options.file)
    if (res.data) {
      model.value.content = res.data
      ElMessage.success('上传成功')
    }
  } catch (error) {
    ElMessage.error('上传失败')
    // 上传失败时移除文件
    const index = content.value.findIndex(item => item.uid === options.file.uid)
    if (index !== -1) {
      content.value.splice(index, 1)
    }
  }
}

const validate = (
  callback: FormValidateCallback = (valid: boolean) =>
    !valid && ElMessage.error({ message: '表单校验不通过', grouping: true })
) =>
  Promise.all([formRef.value].map(e => e?.validate?.(callback)).filter(e => !!e))
    .then((arr: (boolean | undefined)[]) => arr.every(e => e))
    .catch(() => false)

defineExpose({
  init: (id?: string, refresh = true, initData?: Record<string, unknown>) => {
    // 初始化选项
    initRelatedData()
    if (model.value.id === id && !refresh) return

    // 加载数据
    loadData(id).then(() => {
      if (model.value.image) {
        image.value = [
          {
            name: String(new Date().getTime()),
            url: model.value.image,
            status: 'success',
            uid: Date.now()
          }
        ]
      }
      if (model.value.content) {
        content.value = [
          {
            name: String(new Date().getTime()),
            url: model.value.content,
            status: 'success',
            uid: Date.now()
          }
        ]
      }
      if (!id) {
        if (initData) Object.keys(initData).forEach(key => (model.value[key as keyof Banner] = initData[key] as any))
      }
    })
  },
  validate,
  getData: async (relatedLabel = false) => {
    const data: Record<string, unknown> = _.cloneDeep(model.value)
    if (!relatedLabel) return data

    return data
  },
  submit: () => submit(model.value, formRef.value),
  reset: () => {
    formRef.value?.resetFields()
    model.value.id = void 0
    model.value.image = ''
    model.value.content = ''
    image.value = []
    content.value = []
  }
})
</script>

<template>
  <el-form ref="formRef" v-loading="loading" :model="model" label-width="180px" :disabled="disabled">
    <el-row :gutter="18">
      <el-col v-if="!invisibleProps?.includes('title')" :span="24">
        <el-form-item prop="title" label="标题">
          <el-input v-model="model.title" :disabled="disabledProps?.includes('title')" clearable />
        </el-form-item>
      </el-col>
      <el-col v-if="!invisibleProps?.includes('image')" :span="24">
        <el-form-item prop="image" label="轮播图片">
          <!-- <el-input v-model="model.image" :disabled="disabledProps?.includes('image')" clearable /> -->
          <el-upload
            v-model:file-list="image"
            :http-request="imageUpload"
            :on-remove="handleImageFileRemove"
            :limit="1"
            list-type="picture"
          >
            <el-button v-if="!model.image" size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
      </el-col>
      <el-col v-if="!invisibleProps?.includes('content')" :span="24">
        <el-form-item prop="content" label="图片/视频链接">
          <!-- <el-input v-model="model.content" :disabled="disabledProps?.includes('content')" clearable /> -->
          <el-upload
            v-model:file-list="content"
            :http-request="contentUpload"
            :on-remove="handleContentFileRemove"
            :limit="1"
            list-type="picture"
          >
            <el-button v-if="!model.content" size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
      </el-col>
      <el-col v-if="!invisibleProps?.includes('type')" :span="24">
        <el-form-item prop="type" label="跳转图片">
          <el-segmented
            v-model="model.type"
            :options="[
              {
                label: '图片',
                value: '0'
              },
              {
                label: '视频',
                value: '1'
              }
            ]"
          />
        </el-form-item>
      </el-col>
      <el-col v-if="!invisibleProps?.includes('userType')" :span="24">
        <el-form-item prop="userType" label="客户端类型">
          <el-select v-model="model.userType" :disabled="disabledProps?.includes('userType')" filterable clearable>
            <el-option v-for="item in relatedData.clientTypeOptions" :key="item.value" v-bind="item" />
          </el-select>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<style scoped lang="scss">
.option {
  display: flex;
  justify-content: space-between;

  .ext {
    font-size: var(--el-font-size-extra-small);
    color: var(--el-text-color-secondary);
  }
}
</style>
